package com.chixing.config;

import com.chixing.mapper.UserMessageMapper;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;


/**
 * 订单延迟取消队列 配置
 * 使用 TTL + 死信队列 实现15分钟未支付自动取消订单
 */
@Configuration
public class RabbitMQConfig {
    //普通交换机
    public static final String ORDER_EXCHANGE = "order.exchange";
    //订单取消交换机
    public static final String CANCEL_ORDER_EXCHANGE = "order.cancel.exchange";
    //死信交换机
    public static final String ORDER_DEAD_EXCHANGE = "order.dead.exchange";
    //延迟队列
    public static final String ORDER_DELAY_QUEUE = "order.delay.queue";
    //死信队列
    public static final String ORDER_DEAD_QUEUE  = "order.dead.queue";
    //订单取消队列
    public static final String CANCEL_ORDER_QUEUE = "order.cancel.queue";
    //routingKey
    public static final String ORDER_ROUTING_KEY = "order.routing.key";
    public static final String ORDER_DEAD_ROUTING_KEY = "order.dead.routing.key";
    public static final String CANCEL_ORDER_ROUTING_KEY = "order.cancel.key";

    //正常交换机
    @Bean
    public DirectExchange orderExchange(){
        return new DirectExchange(ORDER_EXCHANGE,true,false);
    }

    //订单取消交换机
    @Bean
    public DirectExchange cancelOrderExchange() {
        return new DirectExchange(CANCEL_ORDER_EXCHANGE,true,false);
    }

    //死信交换机
    @Bean
    public DirectExchange orderDeadExchange(){
        return new DirectExchange(ORDER_DEAD_EXCHANGE,true,false);
    }

    //延迟队列
    @Bean
    public Queue orderDelayQueue(){
        return QueueBuilder.durable(ORDER_DELAY_QUEUE)
                .withArgument("x-dead-letter-exchange",ORDER_DEAD_EXCHANGE)
                .withArgument("x-dead-letter-routing-key",ORDER_DEAD_ROUTING_KEY)
                .withArgument("x-message-ttl",2 * 60 * 1000) //1分钟
                .build();
    }

    //死信队列
    @Bean
    public Queue orderDeadQueue(){
        return new Queue(ORDER_DEAD_QUEUE,true);
    }

    //提前取消队列
    @Bean
    public Queue cancelOrderQueue() {
        return new Queue(CANCEL_ORDER_QUEUE, true);
    }

    //绑定延迟队列到正常交换机
    @Bean
    public Binding orderDelayBinding(){
        return BindingBuilder.bind(orderDelayQueue()).to(orderExchange()).with(ORDER_ROUTING_KEY);
    }

    //绑定死信队列到死信交换机
    @Bean
    public Binding orderDeadBinding(){
        return BindingBuilder.bind(orderDeadQueue()).to(orderDeadExchange()).with(ORDER_DEAD_ROUTING_KEY);
    }


    //订单取消队列绑定到交换机
    @Bean
    public Binding cancelOrderBinding(){
        return BindingBuilder.bind(cancelOrderQueue()).to(cancelOrderExchange()).with(CANCEL_ORDER_ROUTING_KEY);
    }

    // ----------------- JSON 转换器 -----------------
    @Bean
    public Jackson2JsonMessageConverter jsonMessageConverter() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册 JavaTimeModule 支持 LocalDate / LocalDateTime
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return new Jackson2JsonMessageConverter(objectMapper);
    }



    // 下单成功队列
    public static final String ORDER_SUCCESS_QUEUE = "order.success.queue";
    public static final String ORDER_SUCCESS_ROUTING_KEY = "order.success";

    // 支付成功队列
    public static final String ORDER_PAYMENT_QUEUE = "order.payment.queue";
    public static final String ORDER_PAYMENT_ROUTING_KEY = "order.payment";

    // 超时自动取消
    public static final String ORDER_TimeOut_QUEUE = "order.timeout.queue";
    public static final String ORDER_TimeOut_ROUTING_KEY = "order.timeout";
    // 延迟支付成功队列
    public static final String ORDER_DELAY_PAYMENT_QUEUE = "order.delay.payment.queue";
    public static final String ORDER_DELAY_PAYMENT_ROUTING_KEY = "order.delay.payment";

    // 队列 + 绑定示例
    @Bean
    public Queue orderSuccessQueue() {
        return new Queue(ORDER_SUCCESS_QUEUE);
    }

    @Bean
    public Binding orderSuccessBinding() {
        return BindingBuilder.bind(orderSuccessQueue())
                .to(orderExchange())
                .with(ORDER_SUCCESS_ROUTING_KEY);
    }

    @Bean
    public Queue orderPaymentQueue() {
        return new Queue(ORDER_PAYMENT_QUEUE);
    }

    @Bean
    public Binding orderPaymentBinding() {
        return BindingBuilder.bind(orderPaymentQueue())
                .to(orderExchange())
                .with(ORDER_PAYMENT_ROUTING_KEY);
    }

    @Bean
    public Queue orderTimeOutQueue(){
        return new Queue(ORDER_TimeOut_QUEUE);
    }

    @Bean
    public Binding orderTimeOutBinding(){
        return BindingBuilder.bind(orderTimeOutQueue()).to(orderExchange()).with(ORDER_TimeOut_ROUTING_KEY);
    }

    @Bean
    public Queue orderDelayPaymentQueue() {
        return new Queue(ORDER_DELAY_PAYMENT_QUEUE);
    }

    @Bean
    public Binding orderDelayPaymentBinding() {
        return BindingBuilder.bind(orderDelayPaymentQueue())
                .to(orderExchange())
                .with(ORDER_DELAY_PAYMENT_ROUTING_KEY);
    }

    // ----------------- RabbitTemplate Bean -----------------
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, UserMessageMapper userMessageMapper) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(jsonMessageConverter());
        rabbitTemplate.setMandatory(true);
        // 确认回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (correlationData != null) {
                System.out.println("ConfirmCallback triggered! correlationData: " + correlationData + ", ack: " + ack + ", cause: " + cause);
                Long userMessageId = Long.valueOf(correlationData.getId());
                if (ack) {
                    userMessageMapper.updateIsPushed(userMessageId);
                    System.out.println("✅ 消息成功投递到 MQ，更新 is_pushed = 1");
                } else {
                    System.err.println("❌ 消息投递失败：" + cause);
                }
            }
        });

        return rabbitTemplate;
    }
}
